package com.gjzt.generator;


import com.eastdigit.data.Constant;
import com.eastdigit.data.DBUtil;
import com.eastdigit.data.DataRow;
import com.eastdigit.data.DataTable;
import com.eastdigit.system.model.Entity;
import com.eastdigit.util.FileUtil;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.*;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/3/17.
 */

/**
 * 代码生成
 * <p>
 * BatisGenerator generator = new BatisGenerator("数据库jar包","driver", "url",
 * "用户名", "密码");
 * <p>
 * generator.addTable("表名", "JavaBean名称", "^替换字符(^表示以开头)",
 * 是否生成controller、service);
 * <p>
 * generator.generate("代码路径");
 */
public class BatisGenerator {

    public static void main(String[] args) {
        BatisGenerator generator = new BatisGenerator(
                "C:\\Users\\Administrator\\.m2\\repository\\mysql\\mysql-connector-java\\5.1.8\\mysql-connector-java-5.1.8.jar",
                "com.mysql.jdbc.Driver",
                "jdbc:mysql://localhost:3306/bus_ad_2?useUnicode=true&characterEncoding=UTF-8",
                "root", "root");
        generator.addTable("MEDIA_EQUIPMENT", "MediaEquipment", "", false);
        generator.generate("com.gjzt.business.media");
    }



    private String jarPath, driverClass, connectionURL, userId, password;
    private List<Table> tables = new ArrayList<Table>();

    public BatisGenerator(String jarPath, String driverClass, String connectionURL, String userId, String password) {
        this.jarPath = jarPath;
        this.driverClass = driverClass;
        this.connectionURL = connectionURL;
        this.userId = userId;
        this.password = password;
    }

    public void clearTable() {
        tables.clear();
    }

    public void addTable(String tableName, String className, String searchString, boolean generatClass) {
        Table table = new Table(tableName, className, searchString, generatClass);
        tables.add(table);
    }

    public void generate(String packageName) {
        String genCfg = "/template/mbgConfiguration.xml";
        InputStream is = this.getClass().getResourceAsStream(genCfg);

        List<String> warnings = new ArrayList<String>();
        ConfigurationParser cp = new ConfigurationParser(warnings);
        try {
            Configuration config = cp.parseConfiguration(is);
            config.getClassPathEntries().clear();
            config.addClasspathEntry(jarPath);

            Context context = config.getContexts().get(0);
            JDBCConnectionConfiguration jdbcConfig = context.getJdbcConnectionConfiguration();
            jdbcConfig.setDriverClass(driverClass);
            jdbcConfig.setConnectionURL(connectionURL);
            jdbcConfig.setUserId(userId);
            jdbcConfig.setPassword(password);

            context.getSqlMapGeneratorConfiguration().setTargetPackage(packageName + ".mapper");
            context.getJavaModelGeneratorConfiguration().setTargetPackage(packageName + ".model");
            context.getJavaClientGeneratorConfiguration().setTargetPackage(packageName + ".inter");

            // 去掉模板里面的
            context.getTableConfigurations().clear();

            for (Table t : tables) {
                TableConfiguration table = new TableConfiguration(context);
                table.setTableName(t.getTableName());
                table.setDomainObjectName(t.getCalssName());
                table.addProperty("rootClass", Entity.class.getName());

                table.setCountByExampleStatementEnabled(false);
                table.setUpdateByExampleStatementEnabled(false);
                table.setDeleteByExampleStatementEnabled(false);
                table.setSelectByExampleStatementEnabled(false);
                table.setSelectByExampleQueryId("false");
                table.setAlias(null);

                ColumnRenamingRule rule = new ColumnRenamingRule();
                rule.setSearchString(t.getSearchString());
                rule.setReplaceString(null);
                table.setColumnRenamingRule(rule);
                context.getTableConfigurations().add(table);
            }

            DefaultShellCallback callback = new DefaultShellCallback(true);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);

            // 创建ControllerAndService
            generateControllerAndService(packageName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void generateControllerAndService(String packageName) throws IOException, TemplateException,
            ClassNotFoundException, SQLException {
        Connection conn = null;
        String projectPath = System.getProperty("user.dir");
        String javaPath = projectPath + "/src/main/java/";
        String javaPackage = javaPath + "/" + packageName.replace(".", "/");
        String controllerPath = javaPackage + "/controller/";
        String servicePath = javaPackage + "/service/";
        FileUtil.mkdir(controllerPath);
        FileUtil.mkdir(servicePath);
        try {
            // 注册数据库驱动
            Class.forName(driverClass);
            // 获取连接
            conn = DriverManager.getConnection(connectionURL, userId, password);

            // 创建一个合适的Configration对象
            String templatePath = BatisGenerator.class.getResource("/").getFile() + "_template";
            FileUtil.mkdir(templatePath);
            FileUtils.copyInputStreamToFile(this.getClass().getResourceAsStream("/template/Controller.ftl"), new File(
                    templatePath + "/Controller.ftl"));
            FileUtils.copyInputStreamToFile(this.getClass().getResourceAsStream("/template/Service.ftl"), new File(
                    templatePath + "/Service.ftl"));

            freemarker.template.Configuration configuration = new freemarker.template.Configuration();
            configuration.setDirectoryForTemplateLoading(new File(templatePath));
            configuration.setObjectWrapper(new DefaultObjectWrapper());
            configuration.setDefaultEncoding(Constant.GLOBAL_CHARSET);

            for (Table t : tables) {
                if (!t.isGeneratClass()) {
                    continue;
                }
                String className = t.getCalssName();
                Map<String, Object> paramMap = new HashMap<String, Object>();
                paramMap.put("PACKAGE_NAME", packageName + ".controller");
                paramMap.put("PARENT_PACKAGE_NAME", packageName);
                paramMap.put("NAME", className);
                paramMap.put("LOWER_NAME", className.substring(0, 1).toLowerCase() + className.substring(1));

                // Controller
                Writer writer = new OutputStreamWriter(new FileOutputStream(controllerPath + className
                        + "Controller.java"), Constant.GLOBAL_CHARSET);
                // 获取或创建一个模版。
                Template template = configuration.getTemplate("Controller.ftl");
                template.process(paramMap, writer);
                writer.close();

                // Service
                DataTable table = DBUtil.getColumnInfo(conn, t.getTableName(), false);
                List<Column> colList = new ArrayList<Column>();
                List<Column> pkList = new ArrayList<Column>();

                int rows = table.getRowCount();
                for (int i = 0; i < rows; i++) {
                    DataRow row = table.getDataRow(i);
                    String columnName = row.getString("COLUMN_NAME");
                    Column cn = new Column();
                    cn.setDataType(row.getInt("DATA_TYPE"));// 数据类型
                    cn.setFormColName(DBUtil.columnNameParser(columnName));// 页面表单

                    if ("Y".equals(row.getString("isKey"))) {// 主键
                        Column pkCn = new Column();
                        String name = cn.getFormColName();
                        pkCn.setFormColName(name);
                        pkCn.setClassColName(name.substring(0, 1).toUpperCase() + name.substring(1));
                        pkCn.setDataType(cn.getDataType());
                        pkList.add(pkCn);
                    }

                    String searchString = t.getSearchString();
                    if (searchString != null) {
                        String[] searchStrings = searchString.split("\\|");
                        for (String search : searchStrings) {
                            if (search.startsWith("^") && row.getString("COLUMN_NAME").startsWith(search.substring(1))) {
                                columnName = columnName.substring(search.length() - 1);
                            } else {
                                columnName = columnName.replace(search, "");
                            }
                        }
                    }
                    columnName = DBUtil.columnNameParser(columnName);
                    cn.setClassColName(columnName.substring(0, 1).toUpperCase() + columnName.substring(1));
                    colList.add(cn);
                }
                paramMap.put("colList", colList);
                paramMap.put("pkList", pkList);
                paramMap.put("PACKAGE_NAME", packageName + ".service");

                writer = new OutputStreamWriter(new FileOutputStream(servicePath + className + "Service.java"),
                        Constant.GLOBAL_CHARSET);
                // 获取或创建一个模版。
                template = configuration.getTemplate("Service.ftl");
                template.process(paramMap, writer);
                writer.close();
            }
            FileUtil.delete(templatePath);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class Table {
        String tableName, calssName, searchString;
        boolean generatClass;

        Table(String tableName, String calssName, String searchString, boolean generatClass) {
            this.tableName = tableName;
            this.calssName = calssName;
            this.searchString = searchString;
            this.generatClass = generatClass;
        }

        public String getTableName() {
            return tableName;
        }

        public String getCalssName() {
            return calssName;
        }

        public String getSearchString() {
            if (searchString == null || !searchString.contains("^C_")) {
                searchString = "^C_|" + searchString;
            }
            return searchString;
        }

        public boolean isGeneratClass() {
            return generatClass;
        }
    }

}
